﻿using AJWPFAdmin.Core.GlobalEvents;
using AJWPFAdmin.Core.HardwareSDKS.Models;
using AJWPFAdmin.Core.Logger;
using AJWPFAdmin.Core.Models.EF.Tables;
using AJWPFAdmin.Services.AppointAPI;
using AJWPFAdmin.Services.EF;
using DocumentFormat.OpenXml.Spreadsheet;
using Microsoft.EntityFrameworkCore;
using Org.BouncyCastle.Asn1.X509;
using Prism.Events;
using Prism.Ioc;
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Interop;

namespace AJWPFAdmin.Services.Jobs
{
    public class AppointAPIUploadFailedRecordJob : IAJJob
    {
        public class AppointAPIUploadFailedRecordQuarztJob : IJob
        {
            public static IList<DeviceInfo> Devices { get; set; }

            public async Task Execute(IJobExecutionContext context)
            {
                if (Devices == null || Devices.Count == 0)
                {
                    return;
                }
                context.MergedJobDataMap.TryGetValue("container", out var container);
                if (container is IContainerProvider provider)
                {
                    var appointApiSvc = new AppointAPISvc(ApplicationType.管理端, provider);

                    if (appointApiSvc.API.Config.Key == Core.Enums.SystemConfigKey.APIDefault)
                    {
                        appointApiSvc.API.Dispose();
                        return;
                    }

                    var logger = provider.Resolve<AJLog4NetLogger>();

                    using var db = DbService.GetDbContext(provider.Resolve<AJConfigService>());

                    var loggerBuilder = new StringBuilder();

                    loggerBuilder.AppendLine($"开始上传同步失败的台账记录");
                    try
                    {
                        var watchhouseIds = Devices.Select(p => new long?(p.WatchhouseId))
                            .Distinct().ToArray();

                        var records = db.ShippingRecords
                            .Where(p =>
                            (watchhouseIds.Contains(p.WarehouseId)) || watchhouseIds.Contains(p.OutWatchhouseId)
                            && !p.Synchronized).ToList();

                        loggerBuilder.AppendLine($"共 {records.Count} 条");

                        foreach (var item in records)
                        {
                            var carNo = item.CarNo;
                            var carInfo = db.Cars.FirstOrDefault(p => p.CarNo == carNo);
                            if (carInfo == null)
                            {
                                continue;
                            }
                            if (!carInfo.Synchronized)
                            {
                                // 先尝试上传车辆信息
                                var carUploadResult = await appointApiSvc.API.UploadCarInfoAsync(new CarInfoParams
                                {
                                    CarInfo = carInfo,
                                    Operation = carInfo.Synchronized ? DataOperationType.更新 : DataOperationType.新增,
                                    Passageway = new Passageway { Direction = item.Direction },
                                    Device = new Device
                                    {
                                        Code = item.Direction == Core.Enums.PassagewayDirection.进
                                                ? item.DeviceCode : item.OutDeviceCode
                                    },
                                });

                                if (!carUploadResult.Success)
                                {
                                    if (!appointApiSvc.API.IgoreErrorKeyWords
                                        .Any(p => carUploadResult.Message.Contains(p)))
                                    {
                                        carInfo.SyncResult = item.SyncResult = $"{carInfo.CarNo} 同步车辆基础台账信息失败:{carUploadResult.Message}";
                                        item.UpdateDate = carInfo.UpdateDate = DateTime.Now;
                                        db.Entry(item).State = EntityState.Modified;

                                    }
                                }
                                else
                                {
                                    carInfo.Synchronized = true;
                                    carInfo.SyncResult = string.Empty;
                                    carInfo.UpdateDate = DateTime.Now;
                                }

                                db.Entry(carInfo).State = EntityState.Modified;
                            }

                            var result = await appointApiSvc.API.UploadShippingRecordAsync(new ShippingRecordParams
                            {
                                Record = item,
                                Operation = DataOperationType.新增,
                            });

                            if (!result.Success)
                            {
                                if (!appointApiSvc.API.IgoreErrorKeyWords.Any(p => result.Message.Contains(p)))
                                {
                                    item.SyncResult = $"{result.Message}";
                                }
                            }
                            else
                            {
                                item.SyncResult = string.Empty;
                            }

                            // 从返回结果读取过车记录和物资的上传次数重新更新
                            var retCopy = result.Attach as UploadShippingRecordResponse;
                            retCopy ??= new UploadShippingRecordResponse();

                            item.Synchronized = retCopy.RecordNum > 0 || retCopy.GoodsNum > 0;
                            item.RecordNum += retCopy.RecordNum;
                            item.GoodsNum += retCopy.GoodsNum;
                            item.UpdateDate = DateTime.Now;
                            db.Entry(item).State = EntityState.Modified;

                        }

                        db.SaveChanges();

                        loggerBuilder.AppendLine("执行完毕");


                    }
                    catch (Exception e)
                    {
                        loggerBuilder.AppendLine($"执行异常:{e.Message}\r\n{e.StackTrace}");
                    }
                    finally
                    {
                        appointApiSvc.API.Dispose();
                    }

                    logger.Info(loggerBuilder.ToString());
                }
            }
        }

        public void Init(IContainerProvider container, IScheduler scheduler)
        {
            var jobData = new Dictionary<string, object> { { "container", container } };
            var map = new JobDataMap
            {
                { "container", container }
            };
            var key = nameof(AppointAPIUploadFailedRecordJob);
            var job = JobBuilder.Create<AppointAPIUploadFailedRecordQuarztJob>().WithIdentity(key)
                .SetJobData(map)
                .WithDescription("第三方放预约接口需要自动上传失败的台账信息的定时任务").Build();

            // 每分钟执行
            var trigger = TriggerBuilder.Create().WithIdentity(key).WithCronSchedule($"0 0/1 * 1/1 * ? *").Build();
            //var trigger = TriggerBuilder.Create().WithDailyTimeIntervalSchedule((b) =>
            //{
            //    b.WithIntervalInSeconds(10);
            //}).Build();

            var _eventAggregator = container.Resolve<IEventAggregator>();

            _eventAggregator.GetEvent<DeviceSetupProgressEvent>().Subscribe((progress) =>
            {
                if (progress.Loading)
                {
                    return;
                }
                AppointAPIUploadFailedRecordQuarztJob.Devices = progress.Devices;
            });

            scheduler.ScheduleJob(job, trigger);
        }
    }
}
